package com.zhiyou.app.shop.website.service.impl;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhiyou.app.shop.website.dao.IStockTypeDao;
import com.zhiyou.app.shop.website.dao.IUserAccountDao;
import com.zhiyou.app.shop.website.dao.IUserStockDao;
import com.zhiyou.app.shop.website.dao.IUserStockInfoDao;
import com.zhiyou.app.shop.website.dao.pojo.StockType;
import com.zhiyou.app.shop.website.dao.pojo.UserAccount;
import com.zhiyou.app.shop.website.dao.pojo.UserStock;
import com.zhiyou.app.shop.website.dao.pojo.UserStockInfo;
import com.zhiyou.app.shop.website.service.IUserStockService;
import com.zhiyou.app.shop.common.util.Page;

@Service(value="userStockService")
public class UserStockService implements IUserStockService {
	private Logger log = Logger.getLogger(UserStockService.class);

	@Autowired
	IStockTypeDao stockTypeDao;
	@Autowired
	IUserStockDao userStockDao;
	@Autowired
	IUserStockInfoDao userStockInfoDao;
	@Autowired
	IUserAccountDao userAccountDao;
	
	public long buyStock(String userId,float money) {//返回买入股票总数
		try{
			long count = 0; //买到的股票总数
			List<StockType> stocks = stockTypeDao.findAll();
			for(StockType stock:stocks){
				if(stock.getRound()>=2){ //c类股票在两轮之后，自动卖出，不在区分交易状态
					String sql = "UPDATE USER_ACCOUNT UA,USER_STOCK US "
							+ " SET UA.addition_money = UA.addition_money + floor(us.stock_num * 0.1 * 0.46), "
							+ " UA.bonus_money =  UA.bonus_money + floor(us.stock_num * 0.1 * 0.46) ,us.stock_num = 0 "
							+ " WHERE UA.user_id = US.User_id AND US.stock_type='C'";
					int columns = userStockDao.execute(sql, null);
					
					//记录交易历史
					String tradeSql = "insert into user_stock_info(id,user_id,stock_quantity,type,price,create_date,trade_date,total_price) "
							+ " select UUID(),us.user_id,us.stock_num,'1',0.1,curdate(),curdate(),us.stock_num*0.1 from user_stock us where us.`stock_type`='C'";
					columns = userStockDao.execute(tradeSql, null);
					
					log.info("卖出所有C类股票，总人数："+columns + "。当前轮数："+stock.getRound() + "写入交易历史记录数："+columns);
					
				}
				//以下开始a、b循环
				if(stock.getAttr1().equals("1")){//attr1交易状态1正在交易，0已结束
					if(stock.getRound()==1){//第一轮 以10%
						long stockNum = (long)Math.floor(money/stock.getCurPrice());
						
						//attr2中存贮总数 total上存贮当前剩余
						String attr2 = stock.getAttr2();
						if(StringUtils.isBlank(attr2)) attr2 = "250000000";
						long total = Integer.parseInt(attr2);
						
						//当前u股票剩余数
						long lastNum = stock.getTotal();
						//计算买入的价格
						//计算要买的总数是不是比剩余的多，如果多，则以下个价格购买，算出剩余的钱
						if(stockNum > lastNum){
							stockNum = lastNum;
							count = count + stockNum;
							money = money - stockNum * stock.getCurPrice();
							//写入买入表
							saveTrade(userId,stock.getType(),lastNum,stock.getCurPrice(),stock.getRound());
							
							saveUserStockInfoBuy(userId,stockNum,stock.getCurPrice());
							//卖出
							saleStock(lastNum,stock.getCurPrice(),stock.getType(),stock.getRound());
							
							stock.setTotal((long)(total*0.1)); //设置目前剩余总数
							float xprice = stock.getCurPrice() + 0.01f;
							DecimalFormat bd = new DecimalFormat("##0.00");
							bd.format(xprice);
							stock.setCurPrice(new BigDecimal(bd.format(xprice)).floatValue()); //设置新的价格
							if(bd.format(xprice).equals("0.2") || bd.format(xprice).equals("0.20") ) {//当前轮已出售完，下轮开始
								stock.setAttr2(String.valueOf(Long.parseLong(stock.getAttr2())*2));
								stock.setCurPrice(0.1f);
								stock.setRound(stock.getRound()+1);
								stock.setAttr1("0");
	
								stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType())*2);
								//将B股设置为可售出
								for(StockType st:stocks){
									if(!st.getType().equalsIgnoreCase(stock.getType())){
										st.setAttr1("1");
										st.setTotal(st.getTotal()*2);
										st.setAttr2(String.valueOf(Long.parseLong(st.getAttr2())*2));
										stockTypeDao.update(st);
										break;
									}
								}
								
								//将所有人的股票数翻倍
								String updateSql = " update user_stock us set us.stock_num = us.stock_num*2 ";
								userStockDao.execute(updateSql, null);
							}
							stockTypeDao.update(stock);
							count = count + buyStock(userId,money);
						}else{
							saveTrade(userId,stock.getType(),stockNum,stock.getCurPrice(),stock.getRound());
							
							stock.setTotal(stock.getTotal() - stockNum);
							if(stock.getTotal() == 0){
								float xprice = stock.getCurPrice() + 0.01f;
								DecimalFormat bd = new DecimalFormat("##0.00");
								bd.format(xprice);
								stock.setCurPrice(new BigDecimal(bd.format(xprice)).floatValue()); //设置新的价格
								if(bd.format(xprice).equals("0.2") || bd.format(xprice).equals("0.20") ) {//当前轮已出售完，下轮开始
									stock.setAttr2(String.valueOf(Long.parseLong(stock.getAttr2())*2));
									stock.setCurPrice(0.1f);
									stock.setRound(stock.getRound()+1);
									stock.setAttr1("0");
		
									stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType())*2);
									for(StockType st:stocks){
										if(!st.getType().equalsIgnoreCase(stock.getType())){
											st.setAttr1("1");
											st.setTotal(st.getTotal()*2);
											st.setAttr2(String.valueOf(Long.parseLong(st.getAttr2())*2));
											stockTypeDao.update(st);
											break;
										}
									}
								}else{
									stock.setTotal((long)(total*0.1)); //设置目前剩余总数
								}
							}
							stockTypeDao.update(stock);
							saveUserStockInfoBuy(userId,stockNum,stock.getCurPrice());
							
							saleStock(stockNum,stock.getCurPrice(),stock.getType(),stock.getRound());
						}
					}else{//所有的股票开始为第二轮
						long stockNum = (long)Math.floor(money/stock.getCurPrice());
						long ptotal = stock.getTotal(); //
						if(stockNum > ptotal){
							money = money - ptotal * stock.getCurPrice();
							
							saveTrade(userId,stock.getType(),ptotal,stock.getCurPrice(),stock.getRound());
							
							saveUserStockInfoBuy(userId,ptotal,stock.getCurPrice());
							saleStock(ptotal,stock.getCurPrice(),stock.getType(),stock.getRound());
							
							float xprice = stock.getCurPrice() + 0.01f;
							DecimalFormat bd = new DecimalFormat("##0.00");
							bd.format(xprice);
							stock.setCurPrice(new BigDecimal(bd.format(xprice)).floatValue()); //设置新的价格
							if(stock.getTotal()==0 || bd.format(xprice).equals("0.2") || bd.format(xprice).equals("0.20")){//说明本轮已经空
								stock.setCurPrice(0.1f);
								stock.setRound(stock.getRound()+1);
								stock.setAttr1("0");
	
								stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType()));
								stock.setAttr2(String.valueOf(Long.parseLong(stock.getAttr2())*2));
								//将所有人的股票数翻倍
								String updateSql = "update user_stock us set us.stock_num = us.stock_num*2 ";
								userStockDao.execute(updateSql, null);
								
								//将另一股设置为可售出
								for(StockType st:stocks){
									if(!st.getType().equalsIgnoreCase(stock.getType())){
										st.setAttr1("1");
										st.setTotal(st.getTotal()*2);
										st.setAttr2(String.valueOf(Long.parseLong(st.getAttr2())*2));
										stockTypeDao.update(st);
										break;
									}
								}
							}
							stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType()));
							stockTypeDao.update(stock);
							count = count + buyStock(userId,money);
						}else{
							saveTrade(userId,stock.getType(),stockNum,stock.getCurPrice(),stock.getRound());
							stock.setTotal(stock.getTotal() - stockNum);
							if(stock.getTotal() == 0){
								float xprice = stock.getCurPrice() + 0.01f;
								DecimalFormat bd = new DecimalFormat("##0.00");
								bd.format(xprice);
								stock.setCurPrice(new BigDecimal(bd.format(xprice)).floatValue()); //设置新的价格
								
								if(bd.format(xprice).equals("0.2") || bd.format(xprice).equals("0.20")){//说明本轮已经空
									stock.setCurPrice(0.1f);
									stock.setRound(stock.getRound()+1);
									stock.setAttr1("0");
		
									stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType()));
									stock.setAttr2(String.valueOf(Long.parseLong(stock.getAttr2())*2));
									//将所有人的股票数翻倍
									String updateSql = "update user_stock us set us.stock_num = us.stock_num*2 ";
									userStockDao.execute(updateSql, null);
									
									//将另一股设置为可售出
									for(StockType st:stocks){
										if(!st.getType().equalsIgnoreCase(stock.getType())){
											st.setAttr1("1");
											st.setTotal(st.getTotal()*2);
											st.setAttr2(String.valueOf(Long.parseLong(st.getAttr2())*2));
											stockTypeDao.update(st);
											break;
										}
									}
								}else{
									stock.setTotal(userStockDao.findByPrice(stock.getCurPrice(), stock.getType()));
								}
							}
							stockTypeDao.update(stock);
							saveUserStockInfoBuy(userId,stockNum,stock.getCurPrice());
							saleStock(stockNum,stock.getCurPrice(),stock.getType(),stock.getRound());
						}
					}
					break;//不在交易状态的股票不再作处理
				}
			}
			return count;
		}catch(Exception e){
			e.printStackTrace();
			return 0;
		}
	}
	
	//卖出股票
	private void saleStock(long stockNum,float price ,String stockType,int round){
		float xprice = price;
		if(round == 1) xprice = 0.1f;
		List<UserStock> list = userStockDao.findByPriceAndType(xprice, stockType,round, 1,10);
		for(UserStock us:list){
			if(stockNum > us.getStockNum()){
				//处理出售后
				UserAccount ua = userAccountDao.findByAccount(us.getUserId());
				if(ua!=null){
					double additionmoney = price * us.getStockNum() * 0.46;
					ua.setAdditionMoney(new BigDecimal(ua.getAdditionMoney().doubleValue()+additionmoney));
					ua.setBonusMoney(new BigDecimal(ua.getBonusMoney().doubleValue()+additionmoney));
					userAccountDao.update(ua);
				}
				saveUserStockInfoSale(us.getUserId(),stockNum,price);

				saleStock(stockNum - us.getStockNum(),price,stockType,round);

				us.setStockNum(0L);
				us.setSaleDate(new Date());
				userStockDao.update(us);
			}else{
				//处理出售后
				UserAccount ua = userAccountDao.findByAccount(us.getUserId());
				if(ua!=null){
					double additionmoney = price * stockNum * 0.46;
					ua.setAdditionMoney(new BigDecimal(ua.getAdditionMoney().doubleValue()+additionmoney));
					ua.setBonusMoney(new BigDecimal(ua.getBonusMoney().doubleValue()+additionmoney));
					userAccountDao.update(ua);
				}
				us.setStockNum(us.getStockNum() - stockNum);
				userStockDao.update(us);
				
				saveUserStockInfoSale(us.getUserId(),stockNum,price);
				break;
			}
		}
	}
	
	//保存购入数据
	private void saveTrade(String userId,String type,long stockNum,float price,int round){
		String sql = "insert into user_stock(user_id,stock_type,stock_num,price,buy_date,round) values ("
				+ ":userid,:type,:num,:price,curdate(),:round) ";
		Map<String,Object> params = new HashMap<String, Object>();
		params.put("userid", userId);
		params.put("type", type);
		params.put("num", stockNum);
		params.put("price", String.valueOf(price));
		params.put("round", round);
		int result = userStockDao.execute(sql, params); 
		log.info("=============：" + result );
	}
	
	private void saveUserStockInfoBuy(String userId,long stockNum,float price){
		saveUserStockInfo(userId,"1",stockNum,price);
	}
	
	
	private void saveUserStockInfoSale(String userId,long stockNum,float price){
		saveUserStockInfo(userId,"0",stockNum,price);
	}
	
	//记录交易历史
	private void saveUserStockInfo(String userid,String type,long stockNum,float price){
		UserStockInfo usi = new UserStockInfo();
		usi.setCreateDate(new Timestamp(System.currentTimeMillis()));
		usi.setTradeDate(usi.getCreateDate());
		usi.setType(type);
		usi.setUserId(userid);
		usi.setStockQuantity((int)stockNum);
		usi.setPrice(new BigDecimal(price));
		usi.setTotalPrice(new BigDecimal(stockNum * price));
		usi.setStatus("1");
		userStockInfoDao.save(usi);
	}

	public void buy() {
		List<UserAccount> list = userAccountDao.findByStock();
		for(UserAccount ua:list){
			buyStock(ua.getUserId(), ua.getStockMoney().floatValue());
		}
	}

	/**
	 * @param type =1  旧股
	 * 		  type =2  新股
	 */
	public Long findUserStock(String account, String type){
		Long stockA = 0l;
		Long stockB = 0l;
		Long stockC = 0l;
		Long stockD = 0l;
		Long stockE = 0l;
		Long stockF = 0l;
		if("1".equals(type)){   //查询旧股   C D E F 
			stockC = userStockDao.findStock(account, "C");
			stockD = userStockDao.findStock(account, "D");
			stockE = userStockDao.findStock(account, "E");
			stockF = userStockDao.findStock(account, "F");
			return stockC + stockD +stockE+ stockF;
		}else if("2".equals(type)){  //查询新股  A  B 
			stockA = userStockDao.findStock(account, "A");
			stockB = userStockDao.findStock(account, "B");
			return stockA + stockB;			
		}
		return stockA + stockB + stockC + stockD +stockE+ stockF;
		/*List<UserStock>  list = userStockDao.findByProperty("userId", account);
		if(list != null && list.size() >0){
			return list.get(0);
		}
		return null;*/
	}
	
	/**
	 * 股票当前价值
	 */
	public BigDecimal findUserStockValue(String account){
		List<UserStock> list = userStockDao.findByProperty("userId", account);
		StockType typeA = new StockType();
		List<StockType> stockTypeA = stockTypeDao.findByProperty("type", "A");
		if(stockTypeA != null && stockTypeA.size() >0){
			typeA = stockTypeA.get(0);
		}
		StockType typeB = new StockType();
		List<StockType> stockTypeB = stockTypeDao.findByProperty("type", "B");
		if(stockTypeB != null && stockTypeB.size() >0){
			typeB = stockTypeB.get(0);
		}
		
		
		/*List<StockType> typelist = stockTypeDao.findByExample(t).findByProperty("attr1", "1");
		float price = 0;
		if(typelist != null && typelist.size() > 0){
			price = typelist.get(0).getCurPrice();
		}*/
		BigDecimal total = BigDecimal.ZERO;
		if(list != null && list.size() >0){
			for (UserStock userStock : list) {
				if("A".equals(userStock.getStockType())){
					total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeA.getCurPrice())));
				}else if("B".equals(userStock.getStockType())){
					total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeB.getCurPrice())));
				}else if("C".equals(userStock.getStockType())){//对于C股票，计算方式仅按当前的股票数*0.1处理就可以了
					total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(0.1)));
					//total += Float.parseFloat(userStock.getPrice())*0.1f;
				}else if("D".equals(userStock.getStockType())){
					//if A.round>1  D*0.19  
					//if A.round=1  D*A股价
					if(typeA.getRound() <= 1){
						total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeA.getCurPrice())));
					}else if(typeA.getRound() > 1){
						total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(0.19)));
					}
					
				}else if("E".equals(userStock.getStockType())){
					if(typeA.getRound() <= 1){
						total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeA.getCurPrice())));
					}else if(typeA.getRound() > 1){
						if(typeB.getCurPrice() >= 0.15){
							total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(0.15)));							
						}else if(typeB.getCurPrice() < 0.15){
							total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeB.getCurPrice())));
						}
					}
				}else if("F".equals(userStock.getStockType())){
					if(typeA.getRound() <= 1){
						total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeA.getCurPrice())));
					}else if(typeA.getRound() > 1){
						if(typeB.getCurPrice() >= 0.17){
							total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(0.17)));							
						}else if(typeB.getCurPrice() < 0.17){
							total = total.add(new BigDecimal(userStock.getStockNum()).multiply(new BigDecimal(typeB.getCurPrice())));
						}
					}
				}
			}
		}
		total = total.setScale(0,BigDecimal.ROUND_DOWN);
		return total;
	}
	public void findUserStock(Page page) {
		UserStock userStock = new UserStock();
		userStockDao.findByExample(page, userStock, Order.desc("buyDate"));
	}
	
	public List<UserStock> getByStockType(String stockType){
		return userStockDao.findByType(stockType);
	}
	
	public void callback(String userids,String stockType,float per){
		String []users = userids.split(",");
		StringBuilder us = new StringBuilder();
		for(String u:users){
			us.append("'"+u+"',");
		}
		Float price =  0.1f;
		if(stockType.equalsIgnoreCase("D")){
			price = 0.19f;
		}else if(stockType.equalsIgnoreCase("E")){
			price = 0.15f;
		}else if(stockType.equalsIgnoreCase("F")){
			price = 0.17f;
		}
		us.append("'-1'");
        //在出售前添加出售记录
        String insert_sql_log = "INSERT INTO USER_STOCK_INFO(ID,USER_ID,STOCK_QUANTITY,TYPE,PRICE,CREATE_DATE,TRADE_DATE,TOTAL_PRICE,STATUS) ";
        insert_sql_log = insert_sql_log + "SELECT UUID(),US.USER_ID,floor(us.stock_num * "+per+"),'0',"+price +
                ",NOW(),NOW(),floor(floor(us.stock_num * "+per+") * "+price+"),'1' FROM USER_STOCK US WHERE US.stock_type='"+stockType+"' and us.User_id in("+us+")";
        userStockDao.execute(insert_sql_log,null);

		String sql = "UPDATE USER_ACCOUNT UA,USER_STOCK US "
				+ " SET UA.addition_money = UA.addition_money + floor(floor(us.stock_num * "+per+") * "+price+" * 0.46), "
				+ " UA.bonus_money =  UA.bonus_money + floor(floor(us.stock_num * "+per+") * "+price+" * 0.46) ,us.stock_num = floor(us.stock_num * (1-"+per+")) "
				+ " WHERE UA.user_id = US.User_id AND US.stock_type='"+stockType+"' and us.User_id in("+us+")";
		int columns = userStockDao.execute(sql, null);
		System.out.println(columns);
	}

	
	public int saveStockSome(String account){
		String updateSql = "UPDATE user_stock us SET us.stock_num = us.stock_num*1.5 WHERE us.user_id='"+account.trim()+"' AND us.stock_type NOT IN ('A','B') ";
		System.out.println(updateSql);
		return userStockDao.execute(updateSql, null);
	}
	
	public List<UserStock> getByUserid(String userid){
		return userStockDao.findByUserId(userid);
	}
	
	public UserStock findById(Integer id){
		return userStockDao.findById(id);
	}
	
	public void save(UserStock us){
		userStockDao.save(us);
	}
	
	public void save(UserStock us,UserStockInfo usi){
		userStockDao.save(us);
		userStockInfoDao.save(usi);
	}
}
